package com.bsf.sonar;

import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.val;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * @author: chejiangyi
 * @create: 2019-05-10 08:58
 */
@Component
public class Sonar {
  @Value("${sonar.url}")
  private String sonarUrl;

  @Value("${sonar.parseformat}")
  private String sonarParseformat;

  private String releateApi =
      "$sonarurl/api/measures/search?projectKeys=$projectName&metricKeys=alert_status,bugs,reliability_rating,vulnerabilities,security_rating,code_smells,sqale_rating,duplicated_lines_density,coverage,ncloc,ncloc_language_distribution";

  public String run(String projectName) {
    try {
      val doc =
          Jsoup.connect(
                  releateApi.replace("$sonarurl", sonarUrl).replace("$projectName", projectName))
              .header("Accept", "*/*")
              .header("Accept-Encoding", "gzip, deflate")
              .header("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
              .header("Content-Type", "application/json;charset=UTF-8")
              .ignoreContentType(true);
      val html = doc.get().body().html();
      JsonResult json = JSON.parseObject(html, JsonResult.class);

      if (json.measures.size() > 0) {
        ParseResult r = new ParseResult();
        json.measures.forEach(
            item -> {
              if (item.metric.equals("bugs")) {
                r.bug = item.value;
              } else if (item.metric.equals("vulnerabilities")) {
                r.leak = item.value;
              } else if (item.metric.equals("code_smells")) {
                r.code_smell = item.value;
              } else if (item.metric.equals("coverage")) {
                r.coverage = item.value;
              } else if (item.metric.equals("duplicated_lines_density")) {
                r.density = item.value;
              } else if (item.metric.equals("alert_status")) {
                r.status = item.value;
              }
            });
        val sonarResult = new String[] {sonarParseformat};
        Arrays.stream(r.getClass().getDeclaredFields())
            .forEach(
                c -> {
                  c.setAccessible(true);
                  try {
                    sonarResult[0] =
                        sonarResult[0].replace("{$" + c.getName() + "}", c.get(r).toString());
                  } catch (Exception e) {
                  }
                });
        return sonarResult[0];
      }
      throw new Exception("访问异常");
    } catch (Exception e) {
      return "访问sonar出错:" + e.getMessage();
    }
  }

  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  private static class JsonResult {
    private ArrayList<Metric> measures = new ArrayList<>();
  }

  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  private static class Metric {
    private String metric;
    private Object value;
  }

  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  private static class ParseResult {
    private Object bug = "[未知]";
    private Object leak = "[未知]";
    private Object code_smell = "[未知]";
    private Object coverage = "[未知]";
    private Object density = "[未知]";
    private Object status = "[未知]";
  }
}
